﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Portal.Data.Crawler
{
    public class Common
    {
        public static string GetHtmlSources(string url)
        {
            var responseFromServer = "";

            try
            {
                var uri = new Uri(url);
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = "GET";
                request.AutomaticDecompression = DecompressionMethods.GZip;
                request.ContentType = "text/html; charset=utf-8";
                request.Host = uri.Host;
                request.Referer = url;
                request.KeepAlive = true;
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0";
                request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
                request.Headers["X-Requested-With"] = "XMLHttpRequest";
                var response = (HttpWebResponse)request.GetResponse();

                var dataStream = response.GetResponseStream();
                if (dataStream != null)
                {
                    var reader = new StreamReader(dataStream);
                    responseFromServer = reader.ReadToEnd();
                    // Clean up the streams.
                    reader.Close();
                    dataStream.Close();
                }
                response.Close();
            }
            catch
            {
                
            }
            return responseFromServer;
        }

        public static string PostHtmlSources(string url, string datas)
        {
            var responseFromServer = "";

            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(datas);
                var uri = new Uri(url);
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.AutomaticDecompression = DecompressionMethods.GZip;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
                request.ContentLength = bytes.Length;
                request.Host = uri.Host;
                request.Referer = url;
                request.KeepAlive = true;
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36";
                request.Accept = "*/*";
                Stream dataStream = request.GetRequestStream();
                dataStream.Write(bytes, 0, bytes.Length);
                dataStream.Close();

                var response = request.GetResponse();
                var responseStream = response.GetResponseStream();
                if (responseStream != null)
                {
                    var reader = new StreamReader(responseStream);
                    responseFromServer = reader.ReadToEnd();
                    // Clean up the streams.
                    reader.Close();
                    responseStream.Close();
                }
                response.Close();
            }
            catch
            {
            }
            return responseFromServer;
        }

        public static string GetFirstImg(string sContent)
        {
            var parser = new HtmlParser();
            var imgs = parser.GetContentInNode(sContent, "<img ", ">");
            if (imgs.Count > 0)
            {
                var srcs = parser.GetProperty(imgs[0], "src");
                if (srcs.Count > 0)
                {
                    return srcs[0].Groups[4].Value;
                }
            }
            return null;
        }

        /// <summary>
        /// Chỉ xóa các dấu tiếng việt
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ConvertChuoiKhongDau(string s)
        {
            Regex regex = new Regex(@"\p{IsCombiningDiacriticalMarks}+");
            string strFormD = s.Normalize(NormalizationForm.FormD);
            return regex.Replace(strFormD, String.Empty).Replace('\u0111', 'd').Replace('\u0110', 'D');
        }

        /// <summary>
        /// Xóa dấu tiếng việt,khoang trang, va cac dau dac biet
        /// </summary>
        public static string RejectMarks(string sInput, string spaceReplacer = "")
        {
            sInput = ConvertChuoiKhongDau(sInput);
            sInput = Regex.Replace(sInput, @"[^A-Za-z0-9_\.~]+", spaceReplacer);
            return sInput;
        }

        public static void RemoveDomain(ref string url)
        {
            if (url.StartsWith("http"))
            {
                var iCut = url.IndexOf("/", 8);
                url = iCut > 0 ? url.Substring(iCut, url.Length - 1) : "#";
            }
        }

        /// <summary>
        /// Dien day du vao duong link
        /// </summary>
        /// <param name="domain">include http, example: http://truyengi.com</param>
        /// <param name="sSource"></param>
        public static void FillFullLink(string domain, ref string sSource)
        {
            var regex = new Regex("[ ]*(src|href)[ ]*=[ ]*\\\"(.*?)\\\"", RegexOptions.IgnoreCase);
            if (String.IsNullOrEmpty(sSource))
            {
                return;
            }
            string str = sSource;
            if (!domain.EndsWith("/"))
                domain += "/";
            foreach (Match match in regex.Matches(sSource))
            {
                string str3 = match.Groups[2].Value;
                if (!str3.StartsWith("http", StringComparison.OrdinalIgnoreCase))
                {
                    string newValue = str3;
                    if (newValue.StartsWith("/"))
                    {
                        newValue = newValue.Remove(0, 1);
                    }
                    newValue = " " + match.Groups[1].Value + "=\"" + domain + newValue + "\" ";
                    str = str.Replace(match.Value, newValue);
                }
            }
            sSource = str;
        }

        /// <summary>
        /// Fill absolute link
        /// </summary>
        /// <param name="domain">include http, example: http://truyengi.com</param>
        /// <param name="link"></param>
        /// <returns></returns>
        public static string FillAbsoluteLink(string domain, string link)
        {
            if (String.IsNullOrEmpty(link)) return "";
            if (!link.StartsWith("http"))
            {
                if (link.StartsWith("/"))
                    link = link.Remove(0, 1);

                if (!domain.EndsWith("/"))
                    domain += "/";
                link = domain + link;
            }
            return link;
        }


        /// <summary>
        /// Xóa tiếng việt, kí tự đặc biệt và chỗ trống thay bằng dấu '-'
        /// </summary>
        public static string ConvertToSafeMarks(string sInput)
        {
            const string specialpattern = @"(""|'|@|&|,|:|;|/|#|%|~|\?|\.)";

            sInput = RejectMarks(sInput, "-");

            sInput = Regex.Replace(sInput, specialpattern, HtmlParser.Patterns.SINGLE_SPACE,
                                   (RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant));

            sInput = Regex.Replace(sInput, HtmlParser.Patterns.MultiSpacePattern, HtmlParser.Patterns.SINGLE_SPACE,
                                   (RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant));

            sInput = Regex.Replace(sInput.Trim(), HtmlParser.Patterns.SINGLE_SPACE, "-",
                                   (RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant));

            sInput = Regex.Replace(sInput, "--", "-");
            if (sInput.EndsWith("-"))
                sInput = sInput.Substring(0, sInput.Length - 1);

            return sInput;
        }

        private static readonly HtmlParser _parser = new HtmlParser();
        /// <summary>
        /// Lay noi dung Truyen tranh theo domain duoc xac dinh san
        /// </summary>
        public static string GetChapBody(string crawlUrl)
        {
            try
            {
                string openDetail = "";
                string closeDetail = "";
                var urlLower = crawlUrl.ToLower();
                if (urlLower.IndexOf("vitaku.com") >= 0)
                {
                    openDetail = "<div class=\"page";
                    closeDetail = "</div>";
                }
                else if (urlLower.IndexOf("comicvn.net") >= 0)
                {
                    openDetail = "<textarea id=\"txtarea";
                    closeDetail = "</textarea>";
                }
                else if (urlLower.IndexOf("blogtruyen.com") >= 0)
                {
                    openDetail = "<article id=\"content";
                    closeDetail = "</article>";
                }
                else if (urlLower.IndexOf("manga24h.com") >= 0)
                {
                    openDetail = "data ='";
                    closeDetail = "';";
                }
                else if (urlLower.IndexOf("truyentranh8.com") >= 0)
                {
                    //danh sach link image
                    openDetail = "lstImages.push(\"";
                    closeDetail = "\");";
                }
                else
                {
                    return "";
                }

                var sources = GetHtmlSources(crawlUrl);
                if (sources.Length > 0)
                {
                    sources = _parser.Replace(sources, HtmlParser.Patterns.BREAK, " ");
                    sources = _parser.Replace(sources, HtmlParser.Patterns.MultiSpacePattern, HtmlParser.Patterns.SINGLE_SPACE);
                    var ss = _parser.GetContentInNode(sources, openDetail, closeDetail);
                    if (ss.Count > 0)
                    {
                        if (urlLower.IndexOf("truyentranh8.com") >= 0)
                        {
                            var newBody = ss.Select(link => link.Substring(openDetail.Length, link.Length - (closeDetail.Length + openDetail.Length))).Aggregate("", (current, realLink) => current + string.Format("<img src=\"{0}\" alt=''/>", realLink));
                            return newBody;
                        }

                        var body = ss[0];
                        if (urlLower.IndexOf("manga24h.com") >= 0)
                        {
                            //remove node bound with special
                            var idx = body.IndexOf("'");
                            body = body.Substring(idx + 1, body.Length - 1 - (closeDetail.Length + idx));
                            var imgUrls = body.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
                            var newBody = imgUrls.Aggregate("", (current, imgUrl) => current + string.Format("<img src=\"{0}\" alt=''/>", imgUrl));
                            return newBody;
                        }

                        else
                        {
                            //remove node bound
                            var idx = body.IndexOf(">");
                            body = body.Substring(idx + 1, body.Length - 1 - (closeDetail.Length + idx));
                            if (urlLower.IndexOf("vitaku.com") >= 0)
                            {
                                body = _parser.RemoveTagAndContentInTags(body, new[] { "div" }); //remove all div+content
                            }
                            else if (urlLower.IndexOf("comicvn.net") >= 0)
                            {
                                body = _parser.RemoveTagOnly(body, new[] { "div", "span", "textarea" });
                            }
                            else if (urlLower.IndexOf("blogtruyen.com") >= 0)
                            {
                                body = _parser.RemoveTagOnly(body, new[] { "div", "article" });
                            }
                            return _parser.RemoveProperties(body, new[] { "width", "height" });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return "";
        }
    }
}
